home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / sendmail.8.8.4.tar.gz / sendmail.8.8.4.tar / sendmail-8.8.4 / contrib / re-mqueue.pl < prev    next >
Perl Script  |  1996-08-06  |  8KB  |  204 lines

  1. #!/usr/bin/perl
  2. #
  3. # re-mqueue -- requeue messages from queueA to queueB based on age.
  4. #
  5. #    Contributed by Paul Pomes <ppomes@Qualcomm.COM>.
  6. #        http://www.qualcomm.com/~ppomes/
  7. #
  8. # Usage: re-mqueue [-d] queueA queueB seconds
  9. #
  10. #  -d        enable debugging
  11. #  queueA    source directory
  12. #  queueB    destination directory
  13. #  seconds    select files older than this number of seconds 
  14. #
  15. # Example: re-mqueue /var/spool/mqueue /var/spool/mqueue2 2700
  16. #
  17. # Moves the qf* and df* files for a message from /var/spool/mqueue to
  18. # /var/spool/mqueue2 if the df* file is over 2700 seconds old.
  19. #
  20. # The qf* file can't be used for age checking as it's partially re-written
  21. # with the results of the last queue run.
  22. #
  23. # Rationale: With a limited number of sendmail processes allowed to run,
  24. # messages that can't be delivered immediately slow down the ones that can.
  25. # This becomes especially important when messages are being queued instead
  26. # of delivered right away, or when the queue becomes excessively deep.
  27. # By putting messages that have already failed one or more delivery attempts
  28. # into another queue, the primary queue can be kept small and fast.
  29. #
  30. # On postoffice.cso.uiuc.edu, the primary sendmail daemon runs the queue
  31. # every thirty minutes.  Messages over 45 minutues old are moved to
  32. # /var/spool/mqueue2 where sendmail runs every hour.  Messages more than
  33. # 3.25 hours old are moved to /var/spool/mqueue3 where sendmail runs every
  34. # four hours.  Messages more than a day old are moved to /var/spool/mqueue4
  35. # where sendmail runs three times a day.  The idea is that a message is
  36. # tried at least twice in the first three queues before being moved to the
  37. # old-age ghetto.
  38. #
  39. # (Each must be re-formed into a single line before using in crontab)
  40. #
  41. # 08 * * * *    /usr/local/libexec/re-mqueue /var/spool/mqueue ##                        /var/spool/mqueue2 2700
  42. # 11 * * * *    /usr/lib/sendmail -oQ/var/spool/mqueue2 -q > ##                            > /var/log/mqueue2 2>&1
  43. # 38 * * * *    /usr/local/libexec/re-mqueue /var/spool/mqueue2
  44. #                    /var/spool/mqueue3 11700
  45. # 41 1,5,9,13,17,21 * * * /usr/lib/sendmail -oQ/var/spool/mqueue3 -q ##                            > /var/log/mqueue3 2>&1
  46. # 48 * * * *    /usr/local/libexec/re-mqueue /var/spool/mqueue3
  47. #                    /var/spool/mqueue4 100000
  48. #53 3,11,19 * * * /usr/lib/sendmail -oQ/var/spool/mqueue4 -q > ##                            > /var/log/mqueue4 2>&1
  49. #
  50. #
  51. # N.B., the moves are done with link().  This has two effects: 1) the mqueue*
  52. # directories must all be on the same filesystem, and 2) the file modification
  53. # times are not changed.  All times must be cumulative from when the df*
  54. # file was created.
  55. #
  56. # Copyright (c) 1995 University of Illinois Board of Trustees and Paul Pomes
  57. # All rights reserved.
  58. #
  59. # Redistribution and use in source and binary forms, with or without
  60. # modification, are permitted provided that the following conditions
  61. # are met:
  62. # 1. Redistributions of source code must retain the above copyright
  63. #    notice, this list of conditions and the following disclaimer.
  64. # 2. Redistributions in binary form must reproduce the above copyright
  65. #    notice, this list of conditions and the following disclaimer in the
  66. #    documentation and/or other materials provided with the distribution.
  67. # 3. All advertising materials mentioning features or use of this software
  68. #    must display the following acknowledgement:
  69. #       This product includes software developed by the University of
  70. #       Illinois at Urbana and their contributors.
  71. # 4. Neither the name of the University nor the names of their contributors
  72. #    may be used to endorse or promote products derived from this software
  73. #    without specific prior written permission.
  74. #
  75. # THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND
  76. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  77. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  78. # ARE DISCLAIMED.  IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE
  79. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  80. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  81. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  82. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  83. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  84. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  85. # SUCH DAMAGE.
  86. #
  87. # @(#)$Id: re-mqueue,v 1.3 1995/05/25 18:14:53 p-pomes Exp $
  88.  
  89. require "syslog.pl";
  90.  
  91. $LOCK_EX = 2;
  92. $LOCK_NB = 4;
  93. $LOCK_UN = 8;
  94.  
  95. # Count arguments, exit if wrong in any way.
  96. die "Usage: $0 [-d] queueA queueB seconds\n" if ($#ARGV < 2);
  97.  
  98. while ($_ = $ARGV[0], /^-/) {
  99.     shift;
  100.     last if /^--$/;
  101.     /^-d/ && $debug++;
  102. }
  103.  
  104. $queueA = shift;
  105. $queueB = shift;
  106. $age = shift;
  107.  
  108. die "$0: $queueA not a directory\n" if (! -d $queueA);
  109. die "$0: $queueB not a directory\n" if (! -d $queueB);
  110. die "$0: $age isn't a valid number of seconds for age\n" if ($age =~ /\D/);
  111.  
  112. # chdir to $queueA and read the directory.  When a df* file is found, stat it.
  113. # If it's older than $age, lock the corresponding qf* file.  If the lock
  114. # fails, give up and move on.  Once the lock is obtained, verify that files
  115. # of the same name *don't* already exist in $queueB and move on if they do.
  116. # Otherwise re-link the qf* and df* files into $queueB then release the lock.
  117.  
  118. chdir "$queueA" || die "$0: can't cd to $queueA: $!\n";
  119. opendir (QA, ".") || die "$0: can't open directory $queueA for reading: $!\n";
  120. @dfiles = grep(/^df/, readdir(QA));
  121. $now = time();
  122. ($program = $0) =~ s,.*/,,;
  123. &openlog($program, 'pid', 'mail');
  124.  
  125. # Loop through the dfiles
  126. while ($dfile = pop(@dfiles)) {
  127.     print "Checking $dfile\n" if ($debug);
  128.     ($qfile = $dfile) =~ s/^d/q/;
  129.     ($mfile = $dfile) =~ s/^df//;
  130.     if (! -e $dfile || -z $dfile) {
  131.     print "$dfile is gone or zero bytes - skipping\n" if ($debug);
  132.     next;
  133.     }
  134.     if (! -e $qfile || -z $qfile) {
  135.     print "$qfile is gone or zero bytes - skipping\n" if ($debug);
  136.     next;
  137.     }
  138.  
  139.     $mtime = $now;
  140.     ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
  141.      $atime,$mtime,$ctime,$blksize,$blocks) = stat($dfile);
  142.  
  143.     # Compare timestamps
  144.     if (($mtime + $age) > $now) {
  145.     printf ("%s is %d seconds old - skipping\n", $dfile, $now-$mtime) if ($debug);
  146.     next;
  147.     }
  148.  
  149.     # See if files of the same name already exist in $queueB
  150.     if (-e "$queueB/$dfile") {
  151.     print "$queueb/$dfile already exists - skipping\n" if ($debug);
  152.     next;
  153.     }
  154.     if (-e "$queueB/$qfile") {
  155.     print "$queueb/$qfile already exists - skipping\n" if ($debug);
  156.     next;
  157.     }
  158.  
  159.     # Try and lock qf* file
  160.     unless (open(QF, ">>$qfile")) {
  161.     print "$qfile: $!\n" if ($debug);
  162.     next;
  163.     }
  164.     $retval = flock(QF, $LOCK_EX|$LOCK_NB) || ($retval = -1);
  165.     if ($retval == -1) {
  166.     print "$qfile already flock()ed - skipping\n" if ($debug);
  167.     close(QF);
  168.     next;
  169.     }
  170.     print "$qfile now flock()ed\n" if ($debug);
  171.  
  172.     # Show time!  Do the link()s
  173.     if (link("$dfile", "$queueB/$dfile") == 0) {
  174.     &syslog('err', 'link(%s, %s/%s): %m', $dfile, $queueB, $dfile);
  175.     print STDERR "$0: link($dfile, $queueB/$dfile): $!\n";
  176.     exit (1);
  177.     }
  178.     if (link("$qfile", "$queueB/$qfile") == 0) {
  179.     &syslog('err', 'link(%s, %s/%s): %m', $qfile, $queueB, $qfile);
  180.     print STDERR "$0: link($qfile, $queueB/$qfile): $!\n";
  181.     unlink("$queueB/$dfile");
  182.     exit (1);
  183.     }
  184.  
  185.     # Links created successfully.  Unlink the original files, release the
  186.     # lock, and close the file.
  187.     print "links ok\n" if ($debug);
  188.     if (unlink($qfile) == 0) {
  189.     &syslog('err', 'unlink(%s): %m', $qfile);
  190.     print STDERR "$0: unlink($qfile): $!\n";
  191.     exit (1);
  192.     }
  193.     if (unlink($dfile) == 0) {
  194.     &syslog('err', 'unlink(%s): %m', $dfile);
  195.     print STDERR "$0: unlink($dfile): $!\n";
  196.     exit (1);
  197.     }
  198.     flock(QF, $LOCK_UN);
  199.     close(QF);
  200.     &syslog('info', '%s moved to %s', $mfile, $queueB);
  201.     print "Done with $dfile $qfile\n\n" if ($debug);
  202. }
  203. exit 0;
  204.